//
// Created by richa on 2019/11/16.
//

#include <memory.h>
#include <unistd.h>
#include "SimPlc.h"
#include "../modbus/modbus_plugin.h"
#include <cstdio>

//unsigned char M[5100];
//unsigned char Y[22];
//unsigned char X[20];
//unsigned short D[6000];

extern "C" {
thread_local unsigned char *M;
thread_local unsigned char *Y;
thread_local unsigned char *X;
thread_local unsigned short *D;
}



using namespace std;
using namespace Sim;

SimPlc::SimPlc(void (*function1)(), void(*init)(unsigned short * D)) {
    plcThread = thread([function1, this, init]() -> void {
        this->initMemery(init);
#pragma clang diagnostic push
#pragma ide diagnostic ignored "EndlessLoop"
        for (;;) {
            this->mutex->lock();
            function1();
            this->mutex->unlock();
            usleep(1000);
        }
#pragma clang diagnostic pop
    });
    plcThread.detach();
}

modbus_mapping_t *SimPlc::getMbMapping() const {
    return mb_mapping;
}

/**
 * 初始化线程变量的内存
 */
void SimPlc::initMemery(void (*init)(unsigned short * D)) {
    // 初始化完毕前, 不放锁
    {
        std::lock_guard<std::mutex> lock(*this->mutex);
        M = (unsigned char *) malloc(sizeof(unsigned char) * 2100);
        Y = (unsigned char *) malloc(sizeof(unsigned char) * 22);
        X = (unsigned char *) malloc(sizeof(unsigned char) * 22);
        D = (unsigned short *) malloc(sizeof(unsigned short) * 600);

        memset(M, 0, sizeof(unsigned char) * 2100);
        memset(Y, 0, sizeof(unsigned char) * 22);
        memset(X, 0, sizeof(unsigned char) * 22);
        memset(D, 0, sizeof(unsigned short) * 600);

        this->M_p = M;
        this->X_p = X;
        this->Y_p = Y;
        this->D_p = D;

        mb_mapping = modbus_mapping_new(MODBUS_MAX_READ_BITS, 0,
                                        MODBUS_MAX_READ_REGISTERS, 0);
        replace_modbus_mapping_cache(mb_mapping, M, 2100,
                                     nullptr, 0,
                                     nullptr, 0,
                                     D, 600);
        init(D);
        printf("mb_mapping is %p\n", (void *) this->mb_mapping);
        this->initFlag = true;
        printf("M地址初始化:%p\n", (void *) M);
        printf("D地址初始化:%p\n", (void *) D);
    }
    timerThread = thread([this]() -> void {
        this->M_p[2002] = 1;
#pragma clang diagnostic push
#pragma ide diagnostic ignored "EndlessLoop"
        for (;;) {
//            usleep(500000);
            std::this_thread::sleep_for(std::chrono::milliseconds(500));
            {
                std::lock_guard<std::mutex> lockGuard(*this->mutex);
                this->M_p[2002] = 0;
                if (this->M_p[2014] == 0) {
                    this->M_p[2014] = 1;
                } else {
                    this->M_p[2014] = 0;
                }
            }
        }
#pragma clang diagnostic pop
    });
    timerThread.detach();
    this->cv.notify_all();
}
